/**
* \file DGVTableVTK.h
*
* \brief This file defines a class for display data in table form using Qt.
* \author Shekhar S. Chandra, 2008
*
* This file is part of DGV Library.
*
* DGV is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DGV is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DGV.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DGVTableVTK_H
#define DGVTableVTK_H

#include <QtGui/QTableWidget> //For Base Class
#include <QtGui/QtGui>

#include "DGVConsole.h"
#include "DGVPlot.h"
#include "DGVAnimatedScan.h"
#include "DGVSurfacePlotVTK.h"

typedef imageType tableType;

/*!
    \class DGVTableVTK
    \brief This class represents the DGV Table Display object using Qt.
    \author Shekhar S. Chandra, 2008-2009

    The class displays table values using the Qt QTableWidget class. You can do 1D FFTs and 1D plots of rows and columns.
    It also allows the user to do a 1D scan (animation plot) through the data and save as a CSV file.
    It inherits all the members from QTableWidget class.

    Usage Example:
    \code
    DGVTableVTK *tbl = new DGVTableVTK;

    tbl->setName(tblName);
    tbl->setData(newData);
    tbl->generateTable();
    tbl->show();
    \endcode
*/
class DGV_VTK_EXPORT DGVTableVTK : public QTableWidget
{
    Q_OBJECT

public:
    /*!
        \fn DGVTableVTK::DGVTableVTK(QWidget *parent = 0)
        \brief The standard constructor
    */
    DGVTableVTK(QWidget *parent = 0);
    /*!
        \fn DGVTableVTK::~DGVTableVTK()
        \brief The standard destructor
    */
    virtual ~DGVTableVTK();

    /*!
        \fn DGVTableVTK::setName(QString filename)
        \brief Set the name of the table.
    */
    void setName(QString filename);
    /*!
        \fn DGVTableVTK::setItem(int row, int column, tableType value)
        \brief Sets the value into table at position. Automates item creation etc.
    */
    virtual void setItem(int row, int column, tableType value);
    virtual void setItem(int row, int column, QString value);
    /*!
        \fn DGVTableVTK::getItem(int x, int y)
        \brief Returns the data at (x,y) in the table.
    */
    tableType getItem(int x, int y);

    /*!
        \fn DGVTableVTK::loadCSV(const QString filename)
        \brief Loads the CSV file into table. Returns true if successful.
    */
    bool loadCSV(const QString filename);
    /*!
        \fn DGVTableVTK::complexValuedMode(bool complexValues)
        \brief Enable the maintaining of complex values and its display?
    */
	void complexValuedMode(bool complexValues);
	/*!
        \fn DGVTableVTK::isComplexValued()
        \brief Is the table complex valued?
    */
	inline bool isComplexValued()
	{   return complexData; }
	/*!
        \fn DGVTableVTK::linkToImageData(bool link)
        \brief Link the table to image data, important in order for changes
        in the table to be applied to the right data.
    */
	void linkToImageData(bool link);
	/*!
        \fn DGVTableVTK::isLinkedToImage()
        \brief Is the table linked to image data, important in order for changes
        in the table to be applied to the right data.
    */
	inline bool isLinkedToImage()
	{   return linkedToImage; }
    /*!
        \fn DGVTableVTK::setData(Array<tableType,2> &values)
        \brief Sets table up for values provided.
    */
    void setData(Array<tableType,2> &values);
    void setData(Array<tableType,1> &values);
    void setData(Array<Array<tableType,1>,1> &values);
    /*!
        \fn DGVTableVTK::setData(Array<complex<tableType>,2> &values)
        \brief Sets table up for complex 1D values provided.
    */
    void setData(Array<complex<tableType>,2> &values);
    void setData(Array<complex<tableType>,1> &values);
    void setData(Array< Array<complex<tableType>,1>,1 > &values);
    /*!
        \fn DGVTableVTK::setDataSize(int rows, int cols)
        \brief Presizes the table data to given size. Useful for when storing results of transforms.
        Note: Call complexValuedMode if data is going to be complex. Array is initialized in the process.
    */
	void setDataSize(int rows, int cols);
	/*!
        \fn DGVTableVTK::setPrecision(int prec)
        \brief Sets the precision of the values displayed. Default is 8 places.
    */
	inline void setPrecision(int prec)
	{   tablePrecision = prec;  }
	/*!
        \fn DGVTableVTK::getPrecision()
        \brief Gets the precision of the values displayed.
    */
	inline int getPrecision()
	{   return tablePrecision;  }
	/*!
        \fn DGVTableVTK::generateTable()
        \brief Reload table data from internal array
    */
    inline void generateTable()
    {   refresh();  }
    /*!
        \fn DGVTableVTK::reload()
        \brief Reload table data from internal array
    */
    void reload();
    /*!
        \fn DGVTableVTK::absoluteMagnitudeAct()
        \brief View the magnitude of the table data
    */
    void viewMagnitude()
    {   absoluteMagnitudeAct->setChecked(true); refresh();  }
    /*!
        \fn DGVTableVTK::viewingMagnitude()
        \brief Is the table showing the magnitude of the table data
    */
    inline bool viewingMagnitude()
    {   return absoluteMagnitudeAct->isChecked();   }
    /*!
        \fn DGVTableVTK::viewImaginaryPart()
        \brief View the imaginary part of the table data
    */
    void viewImaginaryPart()
    {   imaginaryPartAct->setChecked(true); refresh();  }
    /*!
        \fn DGVTableVTK::viewingImaginaryPart()
        \brief Is the table showing the imaginary part of the table data
    */
    inline bool viewingImaginaryPart()
    {   return imaginaryPartAct->isChecked();   }
    /*!
        \fn DGVTableVTK::viewRealPart()
        \brief View the real part of the table data
    */
    void viewRealPart()
    {   realPartAct->setChecked(true); refresh();   }
    /*!
        \fn DGVTableVTK::viewingRealPart()
        \brief Is the table showing the real part of the table data
    */
    inline bool viewingRealPart()
    {   return realPartAct->isChecked();   }
    /*!
        \fn DGVTableVTK::viewPhase()
        \brief View the phase of the table data
    */
    void viewPhase()
    {   phaseAct->setChecked(true); refresh();   }
    /*!
        \fn DGVTableVTK::viewingPhase()
        \brief Is the table showing the phase of the table data
    */
    inline bool viewingPhase()
    {   return phaseAct->isChecked();   }
    /*!
        \fn DGVTableVTK::isViewChanging()
        \brief Is the phase of the table data being viewed.
    */
    inline bool isViewChanging()
    {   return viewChanging;    }
    /*!
        \fn DGVTableVTK::data()
        \brief Returns a Blitz++ array containing the table data.
    */
    Array<tableType,2>& data();
    /*!
        \fn DGVTableVTK::dataComplex()
        \brief Returns a Complex Valued Blitz++ array containing the image data.
    */
	Array<complex<tableType>,2>& dataComplex();
	/*!
        \fn DGVImageVTK::dataViewing()
        \brief Returns a Blitz++ array containing the image data currently being display.
        For complex based tables, the relevant part being viewed is returned. If not is complex valued mode
        this behaves like the data() member.
    */
	Array<tableType,2>& dataViewing();
    /*!
        \fn DGVTableVTK::strippedName()
        \brief Returns the stripped (path removed) name of the table.
    */
    QString strippedName();
    /*!
        \fn DGVTableVTK::strippedNamePrefix()
        \brief Returns the stripped (path removed) name of the table with "Table" prefix.
    */
    QString strippedNamePrefix();
    /*!
        \fn DGVTableVTK::addToContextMenu(QVector<QMenu*> &menus)
        \brief Adds the menu to the context menu. Connections are assumed to be made before hand.
	*/
	void addToContextMenu(QVector<QMenu*> &menus);
    /*!
        \fn DGVTableVTK::setConsole(DGVConsole *newConsole)
        \brief Assigns a console for message output. You should set this before calling data members to ensure
        messages reach the console (if one is present).
	*/
	void setConsole(DGVConsole *newConsole);
	/*!
        \fn DGVTableVTK::setVerboseMode(bool verbose)
        \brief Verbose mode for message output.
	*/
	inline void setVerboseMode(bool verbose)
	{   verboseMode = verbose;  }

    /*!
        \fn DGVTableVTK::data()
        \brief Clears the internal Blitz++ array containing the table data.
    */
    inline void clearArray()
    {   tableData.free();  }

public slots:
    /*!
        \fn DGVTableVTK::zapSelection()
        \brief Sets the selection to zero.
    */
    void zapSelection();
    /*!
        \fn DGVTableVTK::delSelection()
        \brief Deletes the selection.
    */
    void delSelection();
    /*!
        \fn DGVTableVTK::plotSelection()
        \brief Plots the selection.
    */
    void plotSelection();
    /*!
        \fn DGVTableVTK::fftSelection()
        \brief 1D FFT of the selection.
    */
    void fftSelection();
    /*!
        \fn DGVTableVTK::ifftSelection()
        \brief Inverse 1D FFT of the selection.
    */
    void ifftSelection();
    /*!
        \fn DGVTableVTK::fftRealSelection()
        \brief 1D Real FFT of the selection.
    */
    void fftRealSelection();
    /*!
        \fn DGVTableVTK::ifftRealSelection()
        \brief Inverse Real 1D FFT of the selection.
    */
    void ifftRealSelection();
    /*!
        \fn DGVTableVTK::surfacePlotSelection()
        \brief Surface Plots the selection.
    */
    void surfacePlotSelection();
    /*!
        \fn DGVTableVTK::scanSelection()
        \brief Scans through the selection using line plot.
    */
    void scanSelection();
    /*!
        \fn DGVTableVTK::saveSelection()
        \brief Save the selection using CSV file.
    */
    void saveSelection();
    /*!
        \fn DGVTableVTK::saveAll()
        \brief Save the entire table using CSV file.
    */
    void saveAll();
    /*!
        \fn DGVTableVTK::refresh()
        \brief Sets up table data from internal array.
    */
    void refresh();
    /*!
        \fn DGVTableVTK::renameData()
        \brief Renames the table data.
    */
    void renameData();
    /*!
        \fn DGVTableVTK::updateData(int row, int col)
        \brief Updates array values to match table.
    */
    void updateData(int row, int col);

signals:
    /*!
        \fn DGVTableVTK::plotAvailable(DGVPlot *)
        \brief Send signal that a plot is available for showing.
    */
    void plotAvailable(DGVPlot *);
    /*!
        \fn DGVTableVTK::animationAvailable(DGVAnimatedScan *)
        \brief Send signal that a scan is available for showing.
    */
    void animationAvailable(DGVAnimatedScan *);
    /*!
        \fn DGVTableVTK::surfacePlotAvailable(DGVSurfacePlotVTK *)
        \brief Send signal that a surface plot is available for showing.
    */
    void surfacePlotAvailable(DGVSurfacePlotVTK *);
    /*!
        \fn DGVTableVTK::fftSelectionAvailable(Array<complex<tableType>,1> selectedData)
        \brief Send signal that FFT selection has been made and 1D FFT is to be done.
    */
    void fftSelectionAvailable(Array<Array<complex<tableType>,1>,1> selectedData);
    /*!
        \fn DGVTableVTK::ifftSelectionAvailable(Array<complex<tableType>,1> selectedData)
        \brief Send signal that FFT selection has been made and 1D FFT is to be done.
    */
    void ifftSelectionAvailable(Array<Array<complex<tableType>,1>,1> selectedData);
    /*!
        \fn DGVTableVTK::fftRealSelectionAvailable(Array<tableType,1> selectedData)
        \brief Send signal that FFT selection has been made and 1D FFT is to be done.
    */
    void fftRealSelectionAvailable(Array<Array<tableType,1>,1> selectedData);
    /*!
        \fn DGVTableVTK::ifftRealSelectionAvailable(Array<complex<tableType>,1> selectedData)
        \brief Send signal that FFT selection has been made and 1D FFT is to be done.
    */
    void ifftRealSelectionAvailable(Array<Array<complex<tableType>,1>,1> selectedData);
    /*!
        \fn DGVTableVTK::recentFileAvailable(const QString &fileName)
        \brief Send signal that a recent filename is available for saving.
    */
    void recentFileAvailable(const QString &fileName);
    /*!
        \fn DGVTableVTK::nameChanged(const QString newName)
        \brief Send signal that the window has been renamed.
    */
    void nameChanged(const QString newName);

protected:
    bool complexData; //!< Contains complex data?
    bool linkedToImage; //!< Is the table linked to image data? (Used to update the correct data)
    bool viewChanging; //!< Is only the view changing (from viewing imaginary to real etc.) then dont update data.
    bool verboseMode; //!< Verbose messaging mode
    bool consoleAssigned; //!< Messaging console has been set
    bool editable; //!< Flag for maintaining if data is editable
    int tablePrecision; //!< Precision of the decimals. Default is 8.
    QString name; //!< Name of the table.

    //Context Menu
    QMenu *contextMenu; //!< Context Menu
    QVector<QMenu*> menusToAdd; //!< Conext Menu's to add.
    QActionGroup *selectGroup; //!< Group actions that function on selections
    QAction *zapAct; //!< Action object for zapping a selection.
    QAction *delAct; //!< Action object for deleting a selection.
    //-------------
    QActionGroup *globalGroup; //!< Group actions that function on entire table
    QAction *plotAct; //!< Action object for plotting a selection.
    QAction *fft_1DAct; //!< Action for doing 1D FFT
    QAction *ifft_1DAct; //!< Action for doing 1D inverse FFT
    QAction *fft_Real_1DAct; //!< Action for doing real 1D FFT
    QAction *ifft_Real_1DAct; //!< Action for doing real 1D inverse FFT
    QAction *surfacePlotAct; //!< Action object for surface plotting a selection.
    QAction *scanAct; //!< Action object for scanning through a selection.
    //-------------
    QActionGroup *complexGroup; //!< Grouping for check boxes
    QAction *absoluteMagnitudeAct; //!< Show Absolute Magnitude?
	QAction *imaginaryPartAct; //!< Show Imaginary Part?
	QAction *realPartAct; //!< Show Real Part?
	QAction *phaseAct; //!< Show phase/arg?
    //-------------
    QAction *fitColsAct; //!< Action object to fit to columns.
    QAction *fitRowsAct; //!< Action object to fit to rows.
    QAction *saveAct; //!< Action object for saving the selection.
    QAction *saveAllAct; //!< Action object for saving entire table.
    QAction *refreshAct; //!< Action object for refreshing the display of an table.
    QAction *renameAct; //!< Action object for renaming the display of an table.
    QAction *closeAct; //!< Action object for closing the table.

    Array<tableType,2> tableData; //!< Array. Empty until data() is called. Then it is assumed that DGVImage is not used and is created.
    Array<complex<tableType>,2> tableComplexData; //!< Array. Empty until data() is called. Then it is assumed that DGVImage is not used and is created.

    DGVConsole *console; //!< Console for message output

    /*!
		\fn DGVTableVTK::addContextMenuExtras()
		\brief Adds extra parts to context menu. Assumes call is always made inside contextMenuEvent().
	*/
	void addContextMenuExtras();
    /*!
        \fn DGVTableVTK::contextMenuEvent(QContextMenuEvent *event)
        \brief The context menu setup member
    */
    virtual void contextMenuEvent(QContextMenuEvent *event);
    /*!
        \fn DGVTableVTK::createConnections()
        \brief Sets up the connections between widgets.
    */
    void createConnections();
    void createActions();
    void selectionToArray(Array<Array<tableType,1>,1> &xData, Array<Array<tableType,1>,1> &selectedData);
    void selectionToArray(Array<Array<tableType,1>,1> &xData, Array<Array<complex<tableType>,1>,1> &selectedData);
    /*!
        \fn DGVTableVTK::printError(QString msg)
        \brief Error message wrapper for console.
	*/
	void printError(QString msg);
	/*!
        \fn DGVTableVTK::printWarning(QString msg)
        \brief Warning message wrapper for console.
	*/
	void printWarning(QString msg);
	/*!
        \fn DGVTableVTK::printInfo(QString msg)
        \brief Info message wrapper for console.
	*/
	void printInfo(QString msg);
};



#endif // DGVTableVTK_H
